/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * $Id: PositionData.hpp,v 1.12 2009-09-07 08:36:37 morsko Exp $
 *
 * \file
 * \brief MaCI - Position interface data encoder / decoder
 * \author Antti Maula <antti.maula@tkk.fi>
 */
#ifndef _MACI_POSITIONDATA_HPP_
#define _MACI_POSITIONDATA_HPP_
#include "MaCIData.hpp"
#include "PositionTypes.hpp"
#include <stdio.h>

namespace MaCI {
  namespace Position {
    
    /** Data Encoder/Decoder for the Position Interface.
     *
     * Contains the protocol encoder/decoder for the MaCI-Position
     * interface
     */
    class CPositionData : public MaCI::CMaCIData
    {
    public:
      CPositionData(void);
      ~CPositionData();

      /** Copy constructor for Positiondata.
       */
      CPositionData(const CPositionData &aData);


      /** Assignment operator for Positiondata.
       *
       * Use this with care; each call to this function copies data, 
       * so avoid it if possible.
       */
      CPositionData &operator=(const CPositionData &aData);
      

      /** Decode a BinBag container as PositionData element.
       *
       */
      bool DecodeFrom(gim::binbag::CBinBag *aBinBag = NULL);
      

      /** Reset decoder/Encoder.
       *
       * Resets all fields, except leaves the current BinBag container
       * pointer intact.
       */
      void Reset();
      

      /** Set timestamp element.
       *
       * Sets timestamp element for the container.
       *
       * @param[in] aStamp      Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetTimestamp(const Common::TTimestamp &aStamp);


      /** Set Pose2D element.
       *
       * Sets Pose2D element for the container.
       *
       * @param[in] aPose2D     Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetPose2D(const TPose2D &aPose2D);

      /** Set Pose3D element.
       *
       * Sets Pose3D element for the container.
       *
       * @param[in] aPose3D     Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetPose3D(const TPose3D &aPose3D);


      /** Set Variance2D element.
       *
       * Sets variance2D element for the container.
       *
       * @param[in] aVariance2D Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetVariance2D(const TVariance2D &aVariance2D);

      /** Set Variance3D element.
       *
       * Sets variance3D element for the container.
       *
       * @param[in] aVariance3D Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetVariance3D(const TVariance3D &aVariance3D);

      /** Set Probability element.
       *
       * Sets probability element for the container.
       *
       * @param[in] aProbability Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetProbability(const TProbability &aProbability);


      /** Set TPose2DReference element.
       *
       * Sets reference element for the container.
       *
       * @param[in] aRef        Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetPose2DReference(const TPose2DReference &aRef);
      
        
      /** Set Command element.
       *
       * Sets command element for the container.
       *
       * @param[in] aCommand    Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetCommand(const TCommand &aCommand);
      
      /** Set speed 2D element.
       *
       * Sets speed2D element for the container
       *
       * @param[in] aSpeed2D    Reference to element to copy inside binbag.
       * @return                'true' if the element was succesfully added 
       *                        (did not previously exists) or 'false' on error
       *                        or when the element was already set on this session.
       */
      bool SetSpeed2D(const TSpeed2D &aSpeed2D);
      
      /** Return Common::TTimestamp element pointer.
       * 
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
 
      const MaCI::Common::TTimestamp *GetTimestamp(void) const {
     
        return iTimestampPtr;
	
      }
    
      
      /** Return TPose2D element pointer.
       * 
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
      const TPose2D *GetPose2D(void) const;
    
      
      /** Return TPose3D element pointer.
       * 
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
      const TPose3D *GetPose3D(void) const {
	return iPose3DPtr;

      }


      /** Return TVariance2D element pointer.
       * 
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
      const TVariance2D *GetVariance2D(void) const;

      /** Return TVariance3D element pointer.
       * 
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
      const TVariance3D *GetVariance3D(void) const {
        return iVariance3DPtr;
      }


      /** Return TProbability element pointer.
       * 
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
      const TProbability *GetProbability(void) const {
        return iProbabilityPtr;
      }


      /** Return TCommand element pointer.
       * 
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
      const TCommand *GetCommand(void) const {
        return iCommandPtr;
      }


      /** Return TPose2DReference element pointer.
       *
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
      const TPose2DReference *GetPose2DReference(void) const {
        return iPose2DReferencePtr;
      }
      
      /** Return TSpeed2D element pointer.
       *
       * @return                Returns pointer to element,
       *                        or NULL if no such element exists in the container.
       */
      const TSpeed2D *GetSpeed2D(void) const {
        return iSpeed2DPtr;
      }
      
      /** Print.
       * 
       * \copydoc CMaCIData::Print()
       */
      void Print(const int level) const;

    protected:
    private:
      const Common::TTimestamp *iTimestampPtr; ///< Pointer to timestamp if exists
      const TPose2D *iPose2DPtr;
      const TPose3D *iPose3DPtr;
      const TVariance2D *iVariance2DPtr;
      const TVariance3D *iVariance3DPtr;
      const TProbability *iProbabilityPtr;
      const TPose2DReference *iPose2DReferencePtr;
      const TCommand *iCommandPtr;
      const TSpeed2D *iSpeed2DPtr;
      
      mutable TPose2D iPose2DProjectionFrom3D;
      mutable TPose2D iVariance2DProjectionFrom3D;
    };
  }
  }
#endif
